#!/bin/sh
#
# Copyright (C) 2012, 2013, 2015-2017  Etersoft
# Copyright (C) 2012, 2013, 2015-2017  Vitaly Lipatov <lav@etersoft.ru>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

load_helper epm-packages
load_helper epm-print

# pkg suffix
__print_with_arch_suffix()
{
    local pkg="$1"
    local suffix="$2"
    [ -n "$pkg" ] || return 1
    # do not change if some suffix already exists
    echo "$pkg" | grep -q "(x86-32)$" && echo "$pkg" | sed -e "s|(x86-32)$|.i686|" && return 1
    echo "$pkg" | grep "\.x86_64$" && return 1
    echo "$pkg" | grep "\.noarch$" && return 1
    echo "$pkg" | grep "\.i[56]86$" && return 1
    echo "$pkg$suffix"
}

# add suffix .x86_64 if we have 64 arch
exp_with_arch_suffix()
{
    local suffix

    [ "$DISTRARCH" = "x86_64" ] || { cat ; return ; }
    [ "$DISTRNAME" = "ROSA" ] &&  { cat ; return ; }

    # TODO: it is ok for ALT rpm to remove with this suffix
    # TODO: separate install and remove?
    case $PMTYPE in
        yum-rpm|dnf-rpm)
            suffix=".x86_64"
            ;;
        *)
            cat
            return
            ;;
    esac

    # TODO: use estrlist or some function to do it
    local pkg
    for pkg in $(cat) ; do
        local p
        # check only packages without arch
        p="$(__print_with_arch_suffix "$pkg" .i686)" || { echo "$pkg" ; continue ; }
        # add arch suffix only if arch package already installed (otherwise we don't know package arch)
        is_installed "$p" || { echo "$pkg" ; continue ; }
        echo "$pkg.x86_64"
    done
}


_get_grep_exp()
{
    local def="^$1$"
    [ "$PMTYPE" != "emerge" ] && echo "$def" && return
    # Gentoo hack: support for short package form
    echo "$1" | grep -q "/" && echo "$def" && return
    echo "/$1$"
}

# TODO: combine with -qa (the difference only in return status now)
_shortquery_via_packages_list()
{
    local res=1
    local grepexp
    local firstpkg=$1
    shift

    grepexp=$(_get_grep_exp $firstpkg)

    # TODO: we miss status due grep
    # Note: double call due stderr redirect
    # Note: we use short=1 here due grep by ^name$
    # separate first line for print out command
    (short=1 epm_packages $firstpkg | grep -- "$grepexp") && res=0 || res=1

    local pkg
    for pkg in "$@" ; do
        grepexp=$(_get_grep_exp $pkg)
        (short=1 epm_packages $pkg 2>/dev/null) | grep -- "$grepexp" || res=1
    done

    # TODO: print in query (for user): 'warning: package $pkg is not installed'
    return $res
}

# Note: modified from _shortquery_via_packages_list
# TODO: non optimal double epm packages call
_query_via_packages_list()
{
    local res=1
    local grepexp
    local firstpkg=$1
    shift

    grepexp=$(_get_grep_exp $firstpkg)

    # TODO: we miss status due grep
    # TODO: grep correctly
    # Note: double call due stderr redirect
    # Note: we use short=1 here due grep by ^name$
    # separate first line for print out command
    (short=1 epm_packages $firstpkg) | grep -q -- "$grepexp" && (quiet=1 epm_packages $firstpkg) && res=0 || res=1

    local pkg
    for pkg in "$@" ; do
        grepexp=$(_get_grep_exp $pkg)
        (short=1 epm_packages $pkg 2>/dev/null) | grep -q -- "$grepexp" && (quiet=1 epm_packages $pkg) || res=1
    done

    return $res
}

# internal use only, for installed package
__epm_get_hilevel_nameform()
{
    [ -n "$*" ] || return

    case $PMTYPE in
        apt-rpm)
            # use # as delimeter for apt
            local pkg
            pkg=$(rpm -q --queryformat "%{NAME}=%{SERIAL}:%{VERSION}-%{RELEASE}\n" -- $1)
            # for case if serial is missed
            echo $pkg | grep -q "(none)" && pkg=$(rpm -q --queryformat "%{NAME}#%{VERSION}-%{RELEASE}\n" -- $1)
            # HACK: can use only for multiple install packages like kernel
            echo $pkg | grep -q kernel || return 1
            echo $pkg
            return
            ;;
        yum-rpm|dnf-rpm)
            # just use strict version with Epoch and Serial
            local pkg
            #pkg=$(rpm -q --queryformat "%{EPOCH}:%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n" -- $1)
            #echo $pkg | grep -q "(none)" && pkg=$(rpm -q --queryformat "%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n" -- $1)
            pkg=$(rpm -q --queryformat "%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n" -- $1)
            echo $pkg
            return
            ;;
        *)
            return 1
            ;;
    esac
}

# for local installed packages only
# used from epm remove
__epm_get_hilevel_name()
{
    local i
    for i in $@ ; do
        local pkg
        # get short form in pkg
        # FIXME: where we use it? continue or pkg=$i?
        quiet=1 pkg=$(__epm_query_shortname "$i") || pkg="$i" #continue # drop not installed packages
        # if already short form, skipped
        [ "$pkg" = "$i" ] && echo "$i" && continue
        # try get long form or use short form
        __epm_get_hilevel_nameform "$i" || echo $pkg
    done
}

__epm_query_file()
{
    local CMD

    [ -z "$*" ] && return

    case $PMTYPE in
        *-rpm)
            CMD="rpm -qp"
            [ -n "$short" ] && CMD="rpm -qp --queryformat %{name}\n"
            ;;
        *-dpkg)
            CMD="dpkg-deb --show --showformat=\${Package}-\${Version}\n"
            [ -n "$short" ] && CMD="dpkg-query --show --showformat=\${Package}\n"
            ;;
        *)
            fatal "Do not know command for query file package"
            ;;
    esac

    docmd $CMD -- $@
}

# hack: dpkg -W will print names for removed packages too (until newest Ubuntu)
__epm_query_dpkg_check()
{
    local i
    for i in $@ ; do
        a='' dpkg -s $i >/dev/null 2>/dev/null || return
    done
    return 0
}

__epm_query_name()
{
    local CMD

    [ -z "$*" ] && return

    case $PMTYPE in
        *-rpm)
            CMD="rpm -q"
            ;;
        *-dpkg)
            #docmd dpkg -l $@ | grep "^ii"
            #CMD="dpkg-query -W --showformat=\${Package}-\${Version}\n"
            docmd dpkg-query -W "--showformat=\${Package}-\${Version}\n" -- $@ || return
            __epm_query_dpkg_check $@ || return
            return
            ;;
        npackd)
            docmd npackdcl path --package=$1
            return
            ;;
        conary)
            CMD="conary query"
            ;;
        eopkg)
            showcmd eopkg blame $1
            local str
            str="$(a= eopkg blame $1 | grep "^Name")"
            [ -n "$str" ] || return 1
            echo "$str" | sed -e "s|Name[[:space:]]*: \(.*\), version: \(.*\), release: \(.*\)|\1-\2-\3|"
            return
            ;;
        #homebrew)
        #    showcmd "brew info $1"
        #    local HBRESULT
        #    HBRESULT="$(brew info "$1" 2>/dev/null)" || return
        #    echo "$HBRESULT" | grep -q "Not installed" && return 1
        #    echo "$1"
        #    return 0
        #    ;;
        pacman)
            docmd pacman -Q $@
            return
            ;;
        # TODO: need to print name if exists
        #pkgng)
        #    CMD="pkg info -e"
        #    ;;
        # Note: slackpkg info pkgname
        *)
            # default slow workaround
            _query_via_packages_list $@
            return
            ;;
    esac

    docmd $CMD $@
}

__epm_query_shortname()
{
    local CMD

    [ -z "$*" ] && return

    case $PMTYPE in
        *-rpm)
            showcmd rpm -q --queryformat '%{name}\n' -- $@
            a='' rpm -q --queryformat '%{name}\n' -- $@
            return
            ;;
        *-dpkg)
            #CMD="dpkg-query -W --showformat=\${Package}\n"
            docmd dpkg-query -W "--showformat=\${Package}\n" -- $@ || return
            __epm_query_dpkg_check $@ || return
            return
            ;;
        npackd)
            docmd npackdcl path --package=$1
            return
            ;;
        conary)
            CMD="conary query"
            ;;
        eopkg)
            showcmd eopkg blame $1
            local str
            str="$(a= eopkg blame $1 | grep "^Name")"
            [ -n "$str" ] || return 1
            echo "$str" | sed -e "s|Name[[:space:]]*: \(.*\), version: \(.*\), release: \(.*\)|\1|"
            return
            ;;
        homebrew)
            docmd brew info "$1" >/dev/null 2>/dev/null && echo "$1" && return
            return 1
            ;;
        # TODO: check status
        #pacman)
        #    docmd pacman -Q $@ | sed -e "s| .*||g"
        #    return
        #    ;;

        # TODO: need to print name if exists
        #pkgng)
        #    CMD="pkg info -e"
        #    ;;
        # Note: slackpkg info pkgname
        *)
            # default slow workaround
            _shortquery_via_packages_list $@
            return
            ;;
    esac

    docmd $CMD $@
}


# keep here, all modules and epm-query use is_installed from epm-query
# see epm-installed

# check if pkg is installed
is_installed()
{
    (quiet=1 __epm_query_name "$@") >/dev/null 2>/dev/null
}

filter_pkgnames_to_short()
{
    local names="$(cat)"
    __epm_query_shortname $names
}

epm_query()
{
    [ -n "$pkg_filenames" ] || fatal "Query: package name is missed"

    __epm_query_file $pkg_files || return

    if [ -n "$short" ] ; then
        # shellcheck disable=SC2046
        __epm_query_shortname $(print_name $pkg_names) || return
    else
        # shellcheck disable=SC2046
        __epm_query_name $(print_name $pkg_names) || return
    fi
}
